﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Speech.Recognition;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace VoiceCommand
{
    public partial class Fm_Main : Form
    {

        /// <summary>
        /// 导入模拟键盘的方法
        /// </summary>
        /// <param name="bVk" >按键的虚拟键值</param>
        /// <param name= "bScan" >扫描码，一般不用设置，用0代替就行</param>
        /// <param name= "dwFlags" >选项标志：0：表示按下，2：表示松开</param>
        /// <param name= "dwExtraInfo">一般设置为0</param>
        [DllImport("user32.dll")]
        public static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);

        private SpeechRecognitionEngine _speechRecognition = new SpeechRecognitionEngine();//创建语言识别对象


        private List<Model.VoiceCmd> cmdList = new List<Model.VoiceCmd>();

        private Model.VoiceCmd model = new Model.VoiceCmd();

        private List<Keys> currKeyDown = new List<Keys>();


        public Fm_Main()
        {
            InitializeComponent();
        }
        private void SetVoice()
        {
            _speechRecognition.Dispose();
            StartListening();
        }

        private void StartListening()
        {
            _speechRecognition = new SpeechRecognitionEngine();
            _speechRecognition.LoadGrammarAsync(new DictationGrammar());
            _speechRecognition.SetInputToDefaultAudioDevice();
            _speechRecognition.SpeechRecognized += SpeechRecognitionResponse;
            _speechRecognition.RecognizeAsync(RecognizeMode.Multiple);//启动
        }

        public void SpeechRecognitionResponse(object sender, SpeechRecognizedEventArgs e)
        {
            label_msg.Text = "识别到命令：" + e.Result.Text;
            var model = GetVoiceCmd(e.Result.Text);
            if (model != null)
            {
                RunKeyBtn(model.Btns.ToArray());
            }
        }

        private void RunKeyBtn(Keys[] keys)
        {
            // 按下按键
            foreach (var item in keys)
            {
                keybd_event((byte)item, 0, 0, 0);
            }
            // 松开按键
            foreach (var item in keys)
            {
                keybd_event((byte)item, 0, 2, 0);
            }
        }


        private Model.VoiceCmd GetVoiceCmd(string key)
        {
            var model = cmdList.Find(x => x.Key.Replace("，", ",").Trim().Split(',').ToList().Any(m => m == key));
            return model;
        }

        private void SaveData()
        {
            dataGridView.DataSource = new BindingSource(cmdList, null); ;
            Json.SaveVoiceCmd(cmdList);
            Reset();
        }

        private void Reset()
        {
            tbx_Name.Text = string.Empty;
            tbx_Key.Text = string.Empty;
            tbx_Btn.Text = string.Empty;
            model = new Model.VoiceCmd();
        }


        private void tbx_Btn_KeyDown(object sender, KeyEventArgs e)
        {
            (sender as TextBox).Text = string.Empty;
            currKeyDown.Add(e.KeyCode);
        }


        private void tbx_Btn_KeyUp(object sender, KeyEventArgs e)
        {
            var btns = new List<Keys>();
            var text = string.Empty;
            foreach (Keys key in currKeyDown)
            {
                text += key.ToString() + " + ";
                btns.Add(key);
            }
            text = text.Contains(" + ") ? text.Substring(0, text.LastIndexOf(" + ")) : text;
            (sender as TextBox).Text = text;
            model.Btns = btns;
        }
        private void tbx_Btn_Click(object sender, EventArgs e)
        {
            currKeyDown.Clear();
        }


        private void tbx_Name_TextChanged(object sender, EventArgs e)
        {
            model.Name = (sender as TextBox).Text.Trim();
        }

        private void tbx_Key_TextChanged(object sender, EventArgs e)
        {
            model.Key = (sender as TextBox).Text.Trim();
        }

        private void btn_Ok_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrWhiteSpace(tbx_Key.Text.Trim()))
            {
                MessageBox.Show("关键字不能为空", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            if (string.IsNullOrWhiteSpace(tbx_Btn.Text.Trim()))
            {
                MessageBox.Show("快捷键不能为空", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            cmdList.Add(new Model.VoiceCmd()
            {
                Name = model.Name,
                Key = model.Key,
                BtnStr = tbx_Btn.Text.Trim(),
                Btns = model.Btns
            });
            SaveData();
            SetVoice();
        }

        private void Fm_Main_Load(object sender, EventArgs e)
        {
            cmdList = Json.GetVoiceCmd();
            //在datagridview中添加button按钮
            DataGridViewButtonColumn btn = new DataGridViewButtonColumn();
            btn.Name = "btnModify";
            btn.HeaderText = "操作";
            btn.DefaultCellStyle.NullValue = "删除";
            dataGridView.Columns.Add(btn);
            if (cmdList.Count > 0)
            {
                dataGridView.DataSource = cmdList;
                SetVoice();
            }
            timer.Start();
        }

        private void dataGridView_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            //点击button按钮事件
            if (dataGridView.Columns[e.ColumnIndex].Name == "btnModify" && e.RowIndex >= 0)
            {
                cmdList.RemoveAt(e.RowIndex);
                SaveData();
            }
        }

        private void timer_Tick(object sender, EventArgs e)
        {
            label_msg.Text = "正在识别命令...";
        }
    }
}
